﻿<link rel="stylesheet" type="text/css" href="libs/codemirror/lib/codemirror.css">
<script type="text/javascript" src="libs/jquery/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="libs/chroma.min.js"></script>
<script type="text/javascript" src="libs/codemirror/lib/codemirror.js"></script>
<script type="text/javascript" src="libs/codemirror/mode/javascript/javascript.js"></script>

<script type="text/javascript">

(function($) {
    $('code.lang-js').each(function() {

        var code = this;

        var cm = CodeMirror(function(elt) {
            code.parentNode.replaceChild(elt, code);
            }, {
                value: code.innerHTML.trim(),
                indentUnit: 4,
                mode: 'javascript'
            });

        cm.on('update', function(_cm, change) {
            showColors(_cm);
        });

        var resDisplay = $('<div class="result-display" />')
            .appendTo(cm.display.wrapper.parentNode);

        showColors(cm);

        function showColors(cm) {
            $('.cm-string', cm.display.wrapper).each(styleSpan);
            $('.cm-number', cm.display.wrapper).each(enableSlider);

            // evaluate script
            var src = cm.getDoc().getValue();
            //resDisplay.html('');
            try {

                var s = src.split(';').map(eval);
                resDisplay.html('<ol><li>'+s.map(resRec)
                    .filter(function(d) { return d !== undefined; })
                    .join('</li><li>')+'</li></ol>');

                $('.cm-string', resDisplay).each(styleSpan);

            } catch (e) {
                // console.warn(e);
            }

            function resRec(d) {
                if ($.isArray(d)) {
                    return '['+d.map(d.length > 2 ? resShort : resLong).join(',')+']';
                }
                return resLong(d);

                function resLong(d) {
                    if (typeof d == 'boolean') {
                        return '<span class="cm-number">'+(d ? 'true' : 'false')+'</span>';

                    } else if (typeof d == 'string') {
                        // string color, e.g. hex value
                        return '<span class="cm-string">"'+d+'"</span>';
                    } else if (typeof d == 'object' && d._rgb) {
                        // chroma.js object
                        return '<span class="cm-string cm-color" data-color="'+d.css()+'">'+d.hex()+'</span>';
                    } else if ($.isNumeric(d)) {
                        return '<span class="cm-number">'+round(d,3)+'</span>';
                    } else if ($.isFunction(d)) {
                        var s = '';
                        var dom = d.domain ? d.domain() : [0,1],
                            dmin = Math.min(dom[0], dom[dom.length-1]),
                            dmax = Math.max(dom[dom.length-1], dom[0]);
                        for (var i=0;i<=100;i++) {
                            s += '<span class="grad-step" style="background-color:'+d(dmin + i/100 * (dmax - dmin))+'"></span>';
                        }
                        s += '<span class="domain-min">'+dmin+'</span>';
                        s += '<span class="domain-med">'+((dmin + dmax)*0.5)+'</span>';
                        s += '<span class="domain-max">'+dmax+'</span>';
                        return '<div class="gradient">'+s+'</div>';
                    }
                }

                function resShort(d) {
                    if (typeof d == 'string') {
                        // string color, e.g. hex value
                        return '<span class="cm-string cm-color cm-small" data-color="'+d+'"><span class="cm-hidden-text">\''+chroma(d).hex()+'\'</span></span>';
                    } else if (typeof d == 'object' && d._rgb) {
                        // chroma.js object
                        return '<span class="cm-string cm-color cm-small" data-color="'+d.css()+'"><span class="cm-hidden-text">\''+d.hex()+'\'</span></span>';
                    } else if ($.isNumeric(d)) {
                        return '<span class="cm-number">'+round(d,2)+'</span>';
                    } else if (isNaN(d)) {
                        return '<span class="cm-number cm-nan">NaN</span>';
                    }
                }

                function round(d, p) {
                    var n = Math.pow(10, p);
                    return Math.round(d*n) / n;
                }
            }
        }

        function styleSpan() {
            var span = $(this);
            //setTimeout(function() {
                val = span.data('color') || span.html().replace(/['"]/g, '').trim();
                if (chroma[val]) {
                    span.attr('style', '');
                    return;
                }

                try {
                    var col = chroma(val),
                        l = col.luminance();
                    span.attr('style', [
                        'background-color:'+col.hex(),
                        'color:'+(l <0.5 ? 'white' : 'black'),
                        'opacity:'+col.alpha()
                    ].join(';'));
                } catch (e) {
                    //console.log(e);
                    span.attr('style', '');
                    // not a color, so ignore
                }
            //}, 50);
        }

        function enableSlider() {
            return;
            var span = $(this),
                slider = $('<div></div>').addClass('slider'),
                input = $('<input type="range" />').appendTo(slider);

            span.off('mouseenter').on('mouseenter', function() {
                var v = +span.text(),
                    d = Math.pow(10, Math.max(1, Math.log10(v))),
                    min = v - d,
                    max = v + d;
                input.attr({ min: min, max: max })
                    .prop('value', v);
                console.log('span', v);

                span.append(slider);
            });
            span.off('mouseleave').on('mouseleave', function() {
                //slider.remove();
            });
        }

    });

    var toc = $('<ul />')
        .addClass('toc')
        .appendTo(
            $('<div>')
            .addClass('toc-container')
            .appendTo('.wrap')
        );

    var hue = Math.random() * 360;
    $('h2,h3').each(function() {
        var h = $(this),
            l = h.attr('id'),
            t = h.is('h2');
        toc.append('<li class="'+('level-'+(t ? '1' : '2'))+'"><a style="color:'+chroma.lch(50,80,hue)+'" href="#'+l+'">' + h.text() +'</a></li>');
        hue = (hue + 20) % 360;
        var a = $('<a />')
            .attr('href', '#'+l)
            .html(h.html());
        h.html('').append(a);
    });

    $('h3+h4').each(function(i,el) { el.previousElementSibling.appendChild(el); });

})(jQuery);
</script>
<a href="https://github.com/gka/chroma.js" class="github-corner"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#64CEAA; color:#fff; position: absolute; top: 0; border: 0; right: 0;"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>
<style>
    .github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}
    @keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}
</style>
